home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / networking / short_timeout / hrq.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  4.9 KB  |  180 lines

  1. /*
  2.  * Copyright 1994, Silicon Graphics, Inc. 
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or 
  7.  * duplicated in any form, in whole or in part, without the prior written 
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions 
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or 
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - 
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. /*
  19.  *  hrq.c provides two entry points; host_responds_quickly() and hrqerr().
  20.  *
  21.  *  host_responds_quickly sends an ICMP echo request to the remote host
  22.  *  whose name is the only parameter to the function.  It sets a very
  23.  *  short timer, and reports whether the remote host sends an ICMP echo
  24.  *  reply before the timer expires.  host_responds_quickly can be
  25.  *  incorporated into a program similar to a no-frills version of ping,
  26.  *  but one in which the timeout period is mercifully brief.
  27.  *
  28.  *  hrqerr translates integer error codes from host_responds_quickly into
  29.  *  human readable strings.
  30.  *
  31.  *  Author:  Aaron Schuman
  32.  */
  33.  
  34. #include <stdio.h>
  35. #include <sys/time.h>
  36. #include <sys/types.h>
  37. #include <sys/signal.h>
  38. #include <sys/socket.h>
  39. #include <netinet/in_systm.h>
  40. #include <netinet/in.h>
  41. #include <netinet/ip.h>
  42. #include <netinet/ip_icmp.h>
  43. #include <netdb.h>
  44. #include "hrq.h"
  45.  
  46. #define    FALSE    0
  47. #define    TRUE    1
  48.  
  49. static    int    timer_expired    = FALSE;
  50.  
  51.  
  52. static void
  53. acknowledge_alarm()
  54. {
  55.     timer_expired    = TRUE;
  56. }
  57.  
  58.  
  59. int
  60. host_responds_quickly( char * hostname )
  61. {
  62.     struct hostent *    host_p;
  63.     struct sockaddr        address_buffer;
  64.     struct sockaddr_in *    dst_address =
  65.                 (struct sockaddr_in *) &address_buffer;
  66.     uid_t            my_uid;
  67.     uid_t            my_euid;
  68.     struct    protoent *    protocol;
  69.     int            sockfd;
  70.     const int        data_length    = 56;
  71.     const int        max_ip        = 60;
  72.     const int        max_icmp    = 76;
  73.     const int        packet_size = data_length + max_ip + max_icmp;
  74.     u_char *        packet;
  75.     struct    icmp *        icmp_p;
  76.     u_char            packet_buffer[packet_size];
  77.     int            unique_identifier;
  78.     int            length;
  79.     int            remaining_bytes    = data_length + 8;
  80.     u_short *        current_bytes;
  81.     int            checksum    = 0;
  82.     struct itimerval    newtimer;
  83.     struct itimerval    oldtimer;
  84.     int            max_length;
  85.     struct sockaddr_in    src_address;
  86.  
  87.     /* translate host name to host address */
  88.     host_p = gethostbyname( hostname );
  89.     if ( !host_p )
  90.         return (( HOST_NOT_FOUND == h_errno )
  91.             ? HRQERR_UNKNOWNHOST : HRQERR_GETHOSTBYNAME );
  92.     dst_address->sin_family = host_p->h_addrtype;
  93.     bcopy( host_p->h_addr, (caddr_t)&dst_address->sin_addr,
  94.         host_p->h_length );
  95.  
  96.     /* acquire privilege */
  97.     my_uid  = getuid();
  98.     my_euid = geteuid();
  99.     if ( 0 > setreuid( my_uid, my_euid ))
  100.         return HRQERR_SETREUID;
  101.  
  102.     /* obtain memory resources */
  103.     if ((protocol = getprotobyname("icmp")) == NULL)
  104.         return HRQERR_GETPROTOBYNAME;
  105.     if ((sockfd = socket(AF_INET, SOCK_RAW, protocol->p_proto)) < 0)
  106.         return HRQERR_SOCKET;
  107.     if( (packet = (u_char *)malloc((unsigned)packet_size)) == NULL )
  108.         return HRQERR_MALLOC;
  109.     
  110.     /* send ICMP echo request */
  111.     icmp_p = (struct icmp *)packet_buffer;
  112.     icmp_p->icmp_type = ICMP_ECHO;
  113.     icmp_p->icmp_code = 0;
  114.     icmp_p->icmp_cksum = 0;
  115.     icmp_p->icmp_seq = 0;
  116.     icmp_p->icmp_id = unique_identifier = getpid() & 0xFFFF;
  117.     length = data_length + 8;        /* skip ICMP header */
  118.  
  119.     /* determine packet checksum */
  120.     current_bytes = (u_short *) icmp_p;
  121.     while (( remaining_bytes -= 2) > -1 ) 
  122.         checksum += *current_bytes++;
  123.     if ( remaining_bytes == 1 )
  124.         checksum += *(u_char *) current_bytes ;
  125.     checksum  = ( checksum >> 16 ) + ( checksum & 0xffff );
  126.     checksum += ( checksum >> 16 );
  127.     icmp_p->icmp_cksum = ~checksum;
  128.  
  129.     (void) sendto( sockfd, (char *)packet_buffer, length, 0,
  130.             &address_buffer, sizeof(struct sockaddr) );
  131.  
  132.     /* set alarm */
  133.     newtimer.it_value.tv_sec    = 0;
  134.     newtimer.it_value.tv_usec    = 1000;
  135.     newtimer.it_interval.tv_sec    = 1;
  136.     newtimer.it_interval.tv_usec    = 1000;
  137.     signal( SIGALRM, acknowledge_alarm );
  138.     if (0 > setitimer(ITIMER_REAL, &newtimer, &oldtimer))
  139.         return HRQERR_SETITIMER;
  140.  
  141.     /* receive ICMP echo reply */
  142.     (void) setreuid( my_euid, my_uid );
  143.     while ( !timer_expired )
  144.     {
  145.         max_length  = sizeof( src_address );
  146.         length = recvfrom( sockfd, (char *)packet, packet_size,
  147.                   0, (struct sockaddr *)&src_address, &max_length );
  148.         if ( length < 0 )    /* probably EINTR */
  149.             return TARDY_RESPONSE;
  150.         icmp_p = (struct icmp *)
  151.             ( packet + (((struct ip *) packet)->ip_hl << 2 ));
  152.         if (( icmp_p->icmp_type != ICMP_ECHOREPLY ) ||
  153.                 ( icmp_p->icmp_id != unique_identifier ))
  154.             continue;
  155.         return QUICK_RESPONSE;
  156.     }
  157. }
  158.  
  159.  
  160. static char
  161. hrqerr_messages    [][32] =
  162.     {
  163.         "internal error",
  164.         "gethostbyname",
  165.         "unknown host",
  166.         "setreuid",
  167.         "getprotobyname",
  168.         "socket",
  169.         "malloc",
  170.         "setitimer",
  171.     };
  172.  
  173.  
  174. char *
  175. hrqerr( int status )
  176. {
  177.     return hrqerr_messages [status - HRQERR_FIRST_IN_LIST];
  178. }
  179.  
  180.